package com.wangyadong.hobby.thread;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.IntStream;

public class ReentrantLockDemo {

    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private static final int NUM = 5;
    private static final int tNUM = 100;
    public volatile LinkedList list = new LinkedList();

    public static void main(String[] args) {
        ReentrantLockDemo demo = new ReentrantLockDemo();
        IntStream.range(0, tNUM).forEach(l -> {
            new Thread(() -> {
                demo.add(l);
            }).start();
        });
        for (int i = 0; i < tNUM; i++) {
            new Thread(() -> {
                demo.get();
            }).start();
        }
    }

    public void add(Object obj) {
        lock.lock();
        try {
            if (list.size() == NUM) {
                condition.await();
                condition.signalAll();
            }

            list.add(obj);
            System.out.println(" 当前线程访问 它的name is" + Thread.currentThread().getName() + "\tadd value is " + obj.toString() + "  size() is " + list.size());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }


    public Object get() {
        lock.lock();
        try {
            if (list.size() == 0) {
                condition.signalAll();
                condition.await();
            }
            if (list.size() > 0) {
                Object o = list.getFirst();
                list.removeFirst();
                System.out.println("current list size is " + list.size() + " comsumer is " + Thread.currentThread().getName() + "  \tvisits " + o.toString());
                return o;
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
        return -1;
    }

    public List getList() {
        return list;
    }

}
